from baseSnake import *
import time
import os

GRID_SIZE = 25
SPEED_LOCK_SECONDS = 5

os.environ['SDL_VIDEO_CENTERED'] = '1'

grass = pygame.image.load("icons/tank/grass.gif")
steels = pygame.image.load("icons/tank/steels.gif")
walls = pygame.image.load("icons/tank/walls.gif")
water = pygame.image.load("icons/tank/water.gif")
tankR = pygame.image.load("icons/tank/tankR.gif")
tankL = pygame.image.load("icons/tank/tankL.gif")
tankD = pygame.image.load("icons/tank/tankD.gif")
tankU = pygame.image.load("icons/tank/tankU.gif")
star = pygame.image.load("icons/tank/star.gif")
gameOver = pygame.image.load("icons/tank/gameOver.bmp")
grass = pygame.transform.scale(grass,(GRID_SIZE, GRID_SIZE))
steels = pygame.transform.scale(steels,(GRID_SIZE, GRID_SIZE))
walls = pygame.transform.scale(walls,(GRID_SIZE, GRID_SIZE))
water = pygame.transform.scale(water,(GRID_SIZE, GRID_SIZE))
tankR = pygame.transform.scale(tankR,(GRID_SIZE, GRID_SIZE))
tankL = pygame.transform.scale(tankL,(GRID_SIZE, GRID_SIZE))
tankD = pygame.transform.scale(tankD,(GRID_SIZE, GRID_SIZE))
tankU = pygame.transform.scale(tankU,(GRID_SIZE, GRID_SIZE))
star = pygame.transform.scale(star,(GRID_SIZE, GRID_SIZE))


class tankSnake(Snake):
    def __init__(self, screen_x=1200, screen_y=750, grid_size=25):
        super().__init__(screen_x, screen_y, grid_size)
        self.level = 0
        self.speed = 5
        self.max_speed = 10
        self.max_level = 3

    def level_up(self):
        if self.level < self.max_level:
            self.level += 1

    def speed_up(self):
        if self.speed < self.max_speed:
            self.speed += 1

    def speed_down(self):
        if self.speed > 1:
            self.speed -= 1

    def full_speed(self):
        self.speed = self.max_speed

    def min_speed(self):
        self.speed = 1

    def changespeed(self, curkey):
        if curkey == pygame.K_z:
            self.speed_down()
        if curkey == pygame.K_x:
            self.speed_up()


class tankFood(Food):
    def __init__(self, screen_x=1200, screen_y=750, grid_size=25):
        super().__init__(screen_x, screen_y, grid_size)
        self.kind = 0

    def set_tank_food(self, map):
        if self.rect.x == -self.grid_size:
            self.set()
            if map[self.rect.top // self.grid_size][self.rect.left // self.grid_size] in ['w', 'g']:
                found_blank = False
                for i in range(len(map)):
                    for j in range(len(map[0])):
                        if map[i][j] == ' ':
                            self.rect.top = self.grid_size * i
                            self.rect.left = self.grid_size * j
                            found_blank = True
                            break
                    if found_blank:
                        break
            self.kind = 0
            if random.choice([i for i in range(10)]) == 6:
                self.kind = 1


def init_map(screen, map_file='./configs/tank/gitee_map.txt', screen_x=1200, screen_y=750, grid_size = GRID_SIZE):
    char2icon = {
        'c': grass.convert(),
        's': water.convert(),
        'g': steels.convert(),
        'w': walls.convert()
    }
    h, w = screen_y//grid_size, screen_x//grid_size

    map = []
    for i in range(h):
        map.append([' '] * w)

    with open(map_file, 'r') as f:
        lines = f.readlines()
        f.close()
    for row, line in enumerate(lines):
        # line = line.strip()
        for col, ch in enumerate(line):
            if ch in char2icon.keys():
                screen.blit(char2icon[ch], (col*grid_size, row*grid_size))
                map[row][col] = ch
    return map, char2icon


def show_text(screen, pos, text, color, font_bold = False, font_size = 60, font_italic = False):
    #获取系统字体，并设置文字大小
    cur_font = pygame.font.SysFont("宋体", font_size)
    #设置是否加粗属性
    cur_font.set_bold(font_bold)
    #设置是否斜体属性
    cur_font.set_italic(font_italic)
    #设置文字内容
    text_fmt = cur_font.render(text, 1, color, (0,0,0))
    #绘制文字
    screen.blit(text_fmt, pos)


def tank_snake_runner(screen_x=1200, screen_y=750):
    pygame.init()
    screen_size = (screen_x, screen_y)
    screen = pygame.display.set_mode(screen_size)
    map, char2icon = init_map(screen)
    star.convert()
    gameOver.convert()

    pygame.display.set_caption('Tank Snake')
    clock = pygame.time.Clock()
    scores = 0
    isdead = False
    bug_appeared = False

    # 蛇/食物
    snake = tankSnake(screen_x, screen_y, GRID_SIZE)
    food = tankFood(screen_x, screen_y, GRID_SIZE)

    dirction2tank = {
        pygame.K_RIGHT: tankR.convert(),
        pygame.K_LEFT: tankL.convert(),
        pygame.K_UP: tankU.convert(),
        pygame.K_DOWN: tankD.convert(),
    }

    speed_lock = False
    lock_time = time.time()
    while True:
        if speed_lock and time.time() - lock_time > SPEED_LOCK_SECONDS:
            speed_lock = False
            show_text(screen, (650, screen_y - 40), ' ' * 40, (0, 0, 0), font_size=40)

        if not bug_appeared and snake.level >= 3 and len(snake.body) >= 10:
            bug_map, _ = init_map(screen, './configs/tank/bug_map.txt')
            for i in range(len(bug_map)):
                for j in range(len(bug_map[0])):
                    if bug_map[i][j] != ' ':
                        map[i][j] = bug_map[i][j]
            bug_appeared = True

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                return
            if event.type == pygame.KEYDOWN:
                if event.key in [pygame.K_LEFT, pygame.K_RIGHT, pygame.K_UP, pygame.K_DOWN]:
                    snake.changedirection(event.key)
                if not speed_lock and event.key in [pygame.K_z, pygame.K_x]:
                    snake.changespeed(event.key)
                # 死后按space重新
                if event.key == pygame.K_SPACE and isdead:
                    return tank_snake_runner()

        # 画蛇身 / 每一步+1分
        if not isdead:
            tail, _ = snake.move()
            r, c = tail.top//GRID_SIZE, tail.left//GRID_SIZE
            if map[r][c] == ' ':
                pygame.draw.rect(screen, (0, 0, 0), tail, 0)
            else:
                screen.blit(char2icon[map[r][c]], (tail.left, tail.top))
        for node in snake.body:
            rect, dirction = node
            # pygame.draw.rect(screen, (20, 220, 39), rect, 0)
            screen.blit(dirction2tank[dirction], rect)

        isdead = snake.isdead()
        if isdead:
            # screen.fill((0,0,0))
            # show_text(screen, (100, 500), 'YOU DEAD!', (227, 29, 18), False, 100)
            show_text(screen, (300, 600), 'press space to try again...', (237, 109, 0), False, 30)
            screen.blit(gameOver, (300, 400))
            pygame.display.update()
            continue

        head, _ = snake.body[0]
        r, c = head.top // GRID_SIZE, head.left // GRID_SIZE
        crash = False
        if map[r][c] == 'c':
            snake.min_speed()
            speed_lock = True
            lock_time = time.time()
        elif map[r][c] == 's':
            snake.full_speed()
            speed_lock = True
            lock_time = time.time()
        elif map[r][c] == 'w':
            if snake.level >= 1:
                map[r][c] = ' '
                pygame.draw.rect(screen, (0, 0, 0), head, 0)
                scores += 10
            else:
                crash = True
        elif map[r][c] == 'g':
            if snake.level >= 3:
                map[r][c] = ' '
                pygame.draw.rect(screen, (0, 0, 0), head, 0)
                scores += 100
            else:
                crash = True
        # 显示死亡文字
        if crash:
            isdead = True
            # screen.fill((0,0,0))
            # show_text(screen, (100, 500), 'YOU DEAD!', (227, 29, 18), False, 100)
            show_text(screen, (300, 600), 'press space to try again...', (237, 109, 0), False, 30)
            screen.blit(gameOver, (300, 400))
            pygame.display.update()
            continue

        # 食物处理 / 吃到+50分
        # 当食物rect与蛇头重合,吃掉 -> Snake增加一个Node
        if food.rect == snake.body[0][0]:
            scores += 50
            if food.kind == 1:
                snake.level_up()
            elif food.kind == 0:
                snake.addnode()
            pygame.draw.rect(screen, (0, 0, 0), food.rect, 0)
            food.remove()



        # 食物投递
        food.set_tank_food(map)
        # pygame.draw.rect(screen, (136, 0, 21), food.rect, 0)
        if food.kind == 0:
            screen.blit(tankR, food.rect)
        else:
            screen.blit(star, food.rect)

        # 显示分数文字
        show_text(screen, (50, screen_y - 40), 'Scores: ' + str(scores) + '  ', (223, 223, 223), font_size=40)
        show_text(screen, (250, screen_y - 40), 'speed: ' + str(snake.speed) + '  ', (223, 223, 223), font_size=40)
        show_text(screen, (450, screen_y - 40), 'level: ' + str(snake.level) + '  ', (223, 223, 223), font_size=40)
        if speed_lock:
            show_text(screen, (650, screen_y - 40), 'speed locked!!!', (223, 0, 0), font_size=40)

        pygame.display.update()
        clock.tick(5 + snake.speed)


if __name__ == '__main__':
    tank_snake_runner()

